package com.aiden.architecturecomponenttest.http

import android.arch.lifecycle.LiveData
import retrofit2.*
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
import java.util.concurrent.atomic.AtomicBoolean

class LiveDataCallAdapterFactory: CallAdapter.Factory() {

    override fun get(returnType: Type?, annotations: Array<out Annotation>?, retrofit: Retrofit?): CallAdapter<*, *>? {
        if (returnType !is ParameterizedType) {
            throw IllegalArgumentException("return type must be ParameterizedType")
        }
        val returnClass = getRawType(returnType)
        if (returnClass != LiveData::class.java) {
            throw IllegalArgumentException("return type is not LiveData")
        }
        val type = getParameterUpperBound(0, returnType as ParameterizedType)
        return LiveDataCallAdapter<Any>(type)
    }

    class LiveDataCallAdapter<R>(var type: Type): CallAdapter<R, LiveData<R>> {
        override fun adapt(call: Call<R>?): LiveData<R> {
            return object : LiveData<R>() {
                val flag = AtomicBoolean(false)
                override fun onActive() {
                    super.onActive()
                    if (flag.compareAndSet(false, true)) {
                        call!!.enqueue(object : Callback<R> {
                            override fun onResponse(call: Call<R>?, response: Response<R>?) {
                                postValue(response?.body())
                            }

                            override fun onFailure(call: Call<R>?, t: Throwable?) {
                                postValue(null)
                            }
                        })
                    }
                }
            }
        }

        override fun responseType(): Type {
            return type
        }
    }
}